home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Communication
/
LibraryOfCongress
/
Source
/
Storm.m
< prev
next >
Wrap
Text File
|
1994-05-23
|
16KB
|
688 lines
/*
* Interface for network Library of Congress search service.
*
* Michael Hawley
* MIT Media Laboratory
* 20 Ames Street
* Cambridge, MA 02139
* mike@media-lab.mit.edu
* Copyright (c) 1991 MIT Media Laboratory
* Burn before reading! This means you!!
*
* Please forward any comments/revisions.
*/
#import "Storm.h"
#import "Process.h"
#import <appkit/appkit.h>
#import "MyMenuCell.h"
#import "Defaults.h"
#import "util.h"
@implementation Storm
int StormDebug = 1;
id _status;
id _PutHere;
extern setState(), ReadState(), runState(), access(),
getReport(), sleep(), execState();
int confirm(a,b,c,d) char *a,*b,*c,*d; {
char t[1024];
sprintf(t,a,b,c,d);
return NXRunAlertPanel([NXApp appName],t,"Yes","No",NULL)==1;
}
char *
path(char *s)
/*
* if 's' is in [NXArgv[0]], return [NXArgv[0]]/s.
* (for looking up internal commands and files in .../Opener.app/...).
*/
{
char t[1024], *q, *r;
static char p[1024];
extern char **NXArgv;
*t = '\0';
sscanf(s,"%s",t);
if (!*t || *t=='(') return s;
r = s + strlen(t);
strcpy(p,*NXArgv);
if (q=rindex(p,'/'))
strcpy(q+1,t);
else
strcpy(p,t);
if (access(p,0)==0){
strcpy(p+strlen(p),r);
return p;
}
return s;
}
static void say(s, a,b,c,d) id s; char *a,*b,*c,*d; {
char p[1024];
sprintf(p,a,b,c,d);
[s setStringValue:p];
[s display];
NXPing();
}
void message(a,b,c,d) char *a,*b,*c,*d; {
say(_status,a,b,c,d);
}
/*
* These two routines are for tracking net activity.
*/
static void
monitorMail(subj,body,dest) char *subj, *body, *dest; {
char s[1024];
if (!dest || !*dest) dest = "monitor@tome.media.mit.edu";
if (body && *body) sprintf(s,"echo %s",body);
else strcpy(s,"(whoami ; hostname)");
sprintf(s+strlen(s),"| /usr/ucb/Mail -s \"%s\" %s &",
subj && *subj? subj : [NXApp appName], dest);
system(s);
}
static int eq(char *a, char *b){ return strncmp(a,b,strlen(b))==0; }
static void put(P, fmt, a, b, c, d) id P; char *fmt, *a, *b, *c, *d; {
char p[1024];
sprintf(p,fmt,a,b,c,d);
if (Verbose) printf("+ %s\n",p);
[P puts:p];
}
void Put(fmt, a, b, c, d) char *fmt, *a, *b, *c, *d; {
put(_PutHere,fmt,a,b,c,d);
}
static char *
get(P, s, n) id P; char *s; int n; {
[P gets:s:n];
if (*s && Verbose) printf("> %s",s);
return *s? s : (char *)0;
}
char *
pgets(s,n) char *s; int n; {
[_PutHere gets:s:n];
cleanEsc(s);
return *s? s : (char *)0;
}
char *
pgetsx(s,n) char *s; int n; {
[_PutHere gets:s:n];
return *s? s : (char *)0;
}
char
pgetc() {
char c = [_PutHere getc];
if (c == 27 || c== '['){
while ((c = [_PutHere getc]) != 'H' /* && c != 'm'*/ && c != '\n' && c != '\r') ;
if (c=='H' || c=='m') c = [_PutHere getc];
}
return c;
}
/***
#ifdef 0
static char *
flush(P,s) id P; char *s; {
static char t[1024];
while (get(P,t,sizeof t))
if (strindex(t,s)) return t;
sleep(1);
while (get(P,t,sizeof t))
if (strindex(t,s)) return t;
return (char *)0;
}
#endif
***/
char *
Flush(s) char *s; {
static char t[1024];
if (_PutHere) return (char *)0;
while (get(_PutHere,t,sizeof t))
if (strindex(t,s)) return t;
sleep(1);
while (get(_PutHere,t,sizeof t))
if (strindex(t,s)) return t;
return (char *)0;
}
- enable:(BOOL)b {
[attachB setIcon:b? "plug" : "unplug"];
return self;
}
static id _text, _scroll;
- initMatrix {
// from the nib file, we have the help text; keep a pointer to it.
_text = helpText = [scrollView docView];
[_text setDelegate:self];
[_text setMarginLeft:6.0 right:6.0 top:0.0 bottom:0.0];
[_text notifyAncestorWhenFrameChanged:YES];
return self;
}
- setScrollView:anObject {
_scroll = scrollView = anObject;
[self initMatrix];
return self;
}
extern char DefaultFont[];
extern char DefaultFontSize[];
static id fid = (id)0;
static int canconvert = 0;
// double atof();
char TextBuf[80000]="";
#import <appkit/FontManager.h>
prettyFormat(s) char *s; { // tweak fonts in a card catalog record
char *p = index(s,'\n')+1;
if (*s){ // italicize leading ...: fields
char *q = index(p,':');
while (q && *q == ':'){
[_text setSel:p-s:q-s+1];
[_text setSelFontSize:[fid pointSize]*(12./14.)];
[_text setSelFontStyle:NX_ITALIC];
p = index(q,'\n'); if (p) p++;
if (p && *p) q = index(p,':');
else q = (char *)0;
}
}
}
/*
* This is called as a TimedEntry as a kludge -- the effect we want
* is for the user to change the font in the text view, and then to
* apply the prettyFormat() to it. The problem is that textWillConvert
* will be invoked for every font change and we want to do this
* after the smoke has cleared.
*/
hackToEnforceFonts(DPSTimedEntry n, double now, char *userData) {
if (canconvert && *TextBuf){ // reformat current entry
id w = [_scroll window];
char *s = TextBuf, *p = index(s,'\n')+1;
static NXPoint origin = {0.0,0.0};
DPSRemoveTimedEntry(n);
canconvert=0;
[w disableFlushWindow];
//[_text setText:s];
[_text setSel:p-s:strlen(s)];
[_text setSelGray:0.0];
[_text setSelFont:fid];
prettyFormat(s);
[_text selectNull];
[_text scrollPoint:&origin];
[_scroll display];
[[w reenableFlushWindow] flushWindow];
canconvert=1;
[_text setDelegate:userData];
}
}
- textWillConvert:textObject fromFont:from toFont:to {
if (canconvert && (strcmp(DefaultFont,[from name])==0 ||
atof(DefaultFontSize) == [from pointSize])){
strcpy(DefaultFont,[to name]);
sprintf(DefaultFontSize,"%f",[to pointSize]);
fid = to;
writeDefaults();
[_text setDelegate:0];
DPSAddTimedEntry(0.,hackToEnforceFonts,self,100);
}
return to;
}
void
setText(s) char *s; {
static NXPoint origin = {0.0,0.0};
char *p = index(s,'\n')+1; /* skip past first (blank) line */
id w = [_scroll window];
if (!fid){
fid = [Font newFont:DefaultFont size:atof(DefaultFontSize)];
}
canconvert=0;
[w disableFlushWindow];
[_text setText:s];
[_text setSel:p-s:strlen(s)];
[_text setSelGray:0.0];
[_text setSelFont:fid];
prettyFormat(s);
[_text selectNull];
[_text scrollPoint:&origin];
[_scroll display];
[[w reenableFlushWindow] flushWindow];
canconvert=1;
strcpy(TextBuf,s);
if (TextBuf[0] && index(TextBuf,':')) [[_text delegate] enableOrder];
else [[_text delegate] disableOrder];
}
void
setFile(s) char *s; {
NXStream *f = NXMapFile(path(s),NX_READONLY);
static NXPoint origin = {0.0,0.0};
id w = [_scroll window];
canconvert=0;
s = path(s);
if (!f) return ;
[w disableFlushWindow];
[_text setMonoFont:NO];
[_text readRichText:f];
[_text scrollPoint:&origin];
NXCloseMemory(f,NX_FREEBUFFER);
[_scroll display];
[[w reenableFlushWindow] flushWindow];
TextBuf[0] = '\0';
[[_text delegate] disableOrder];
}
- showHelp:sender {
setFile("info");
return self;
}
#define Case break; case
void
squishRtn(char *s){
char *p = s;
while (*p = *s++)
if (*p != '\r') ++p;
}
static char *
getLine(char *s, char *t){ /* read ...\n from s into t; return new s */
char *p = t;
*t = '\0';
squishRtn(s);
while (*s && *s != '\n') *p++ = *s++;
if (*s == '\n') *p++ = *s++;
*p++ = '\0';
if (*t == '\0') return (char *)0;
p = t;
return s;
}
cleanEsc(s) char *s; {
if (*s == '[' || *s == 27){
char *p = s;
while (*p && *p != '\n' && *p != 'H') ++p;
if (*p == 'H') ++p;
strcpy(s,p);
}
return 1;
}
- processOutput:(char *)s {
static char prev[8192]="";
char t[1024], *p=prev;
{
char *p = s;
while (*p){
if (*p == 27) *p = '\n';
p++;
}
}
strcat(prev,s); s = t;
while ((p=getLine(p,s)) &&
(index(s,'\n') && cleanEsc(s))){
if (Verbose) printf("- %s",s);
execState(0,s);
}
strcpy(prev,blank(s)?s:"");
return self;
}
- hitFormat:sender {
extern setFormat();
extern char *cmdHelpText();
char *s = (char *)[[sender selectedCell] title];
setFormat(s);
[cmdHelp setStringValue:cmdHelpText()];
return self;
}
id _browser;
- query:sender {
char buf[80000];
extern int LastItem;
char *fixQuery(), *s = fixQuery([form stringValueAt:0]);
if (!s || !*s){ // beep
return self;
}
_browser = browser;
enableMore(0);
resetItems(); [browser loadColumnZero];
Put("%s\r",s); pgets(buf,256);
getReport(buf,0);
[browser loadColumnZero];
[form selectTextAt:0];
if (LastItem == 3){
fixItem(buf);
setText(buf);
} else
setText("");
return self;
}
static id me;
void
Command(s) char *s; {
_PutHere = [Process new:s delegate:me];
}
- click:sender {
id c = [[browser matrixInColumn:[browser lastColumn]] selectedCell];
if ([c isLeaf])
[c click:self];
return self;
}
reload(DPSTimedEntry n, double now, char *userData) {
extern int MustReload;
DPSRemoveTimedEntry(n);
if (MustReload) [_browser loadColumnZero], MustReload = 0;
setText("");
}
- (int)browser:sender fillMatrix:matrix inColumn:(int)column {
extern int NI;
return NI;
}
- browser:sender loadCell:c atRow:(int)row inColumn:(int)column {
[c setContents:row];
return self;
}
id _moreB;
- more:sender {
extern int LastItem;
char buf[80000];
Put("n\r"); pgets(buf,256);
getReport(buf,1);
[browser loadColumnZero];
[form selectTextAt:0];
if (LastItem == 3){
fixItem(buf);
setText(buf);
} else
setText("");
return self;
}
enableMore(n){
return [_moreB setEnabled:n];
}
- login:sender {
if (_PutHere) [_PutHere free]; P = _PutHere = (id)0;
_status = status;
_moreB = moreB;
ReadState(path("menus"));
[browser setDelegate:self];
[browser setCellPrototype:[[MyMenuCell alloc] init]];
[browser setAction:@selector(click:)];
[browser setTarget:self];
[attachB setIcon:"plug"];
[form selectTextAt:0];
runState("");
return self;
}
- ready:sender {
resetItems(); [browser loadColumnZero];
[searchB setEnabled:1];
return self;
}
- logout:sender {
if (P && _PutHere) setState("Detach"), runState("");
if (P) [P terminate:self];
_PutHere = P = (id)0;
[self enable:NO];
[attachB setIcon:"unplug"];
[searchB setEnabled:0];
message("not connected.");
return self;
}
void
ready(){
[me ready:me];
}
void
logout(){
[me logout:me];
}
- ensurelogin {
//if (!_PutHere) [self login:self];
return self;
}
int
ensurelogin(){
[me ensurelogin];
return _PutHere? 1 : 0;
}
- attach:sender {
if (eq((char *)[sender icon],"unplug")){
[self login:sender];
} else {
[self logout:sender];
}
return self;
}
/*
* telnet:
*/
- copyString:(char *)s {
id p = [Pasteboard new];
[p declareTypes:&NXAsciiPboard num:1 owner:self];
[p writeType:NXAsciiPboard data:s length:strlen(s)];
return self;
}
- launchTerminal:(char *)program {
id p = [NXApp appSpeaker];
port_t t = NXPortFromName("Terminal",NULL);
int ok;
if (t==PORT_NULL) return self;
[p setSendPort:t];
[self copyString:program];
(void)[p msgPaste:&ok];
return self;
}
- (char *)service {
char *s = "dra.com"; // (char *)[[format selectedCell] title];
return s && *s? s : "192.65.218.43";
}
- telnet:sender {
char s[1024];
sprintf(s,"telnet %s\n", [self service]);
[self launchTerminal:s];
return self;
}
- sendComments:sender {
return self;
}
char *
orderForm(){
static char s[1024]="";
char *h;
if (*s) return s;
h = getenv("HOME");
if (!h || !*h) sprintf(s,"/tmp");
else sprintf(s,"%s/.NeXT",h);
strcat(s,"/BookOrderForm");
}
- editOrder:sender {
if (access(orderForm(),0)){
System("cp %s %s",path("BookOrderForm"),orderForm());
}
System("open %s",orderForm());
return self;
}
- enableOrder {
[orderB setEnabled:YES];
[orderMenuB setEnabled:YES];
return self;
}
- disableOrder {
[orderB setEnabled:NO];
[orderMenuB setEnabled:NO];
return self;
}
- sendOrder:sender {
char t[1024],t2[1024],body[80000], *Body = body;
char to[1024] = "", cc[1024]="", subj[1024]="";
FILE *f;
#define fcall(a) [s performRemoteMethod:a]
#define call(a,b) [s performRemoteMethod:a with:b length:strlen(b)+1]
id s = [NXApp appSpeaker];
if (access(orderForm(),0)){
if (confirm("You need to edit the order form...")){
[self editOrder:self];
//monitorMail("LibraryOfCongress-1.0-order",0,0);
}
return self;
}
strcpy(to,"quanbook@world.std.com");
strcpy(subj,"another e-mail book order");
strcpy(cc,"whoami"); execstr(cc); stripnl(cc);
*body = '\0';
if (strindex(TextBuf,"Type of Material:")){
char *p, c[1024], t[80000];
sprintf(t, "/tmp/book-order%d",getpid());
sprintf(t2,"/tmp/book-info%d",getpid());
System("sed '/^#/d' %s > %s",orderForm(),t);
f = fopen(t2,"w");
if (!f){
confirm("Couldn't create scratch file (%s)",t2);
} else {
write(fileno(f),TextBuf,strlen(TextBuf));
write(fileno(f),"Body:\n",6);
//strcpy(t,TextBuf+1); sub(t,'\t',' ');
write(fileno(f),TextBuf+1,strlen(TextBuf+1));
write(fileno(f),"Body:\n",6);
fclose(f);
}
sprintf(c,"sed '/^[a-zA-Z]* [a-zA-Z ]*:/s/ /_/' %s > %sa",t2,t2);
system(c);
sprintf(c,"%s %s < %sa > %sa",path("rtfcast"),t,t2,t);
system(c);
unlink(t); unlink(t2); strcat(t,"a"); strcat(t2,"a");
f = fopen(t,"r");
if (!f){
confirm("Couldn't read scratch file (%s)",t);
} else {
int n = read(fileno(f),body,sizeof(body));
if (n > 0) body[n] = '\0';
fclose(f);
}
unlink(t); unlink(t2);
if (((p = strindex(Body,"To:")) ||
(p = strindex(Body,"to:"))) &&
(p == Body || p[-1] == '\n')){
sscanf(skipsp(index(p,':')+1),"%[^\n]",to);
if (p==Body) Body = index(p,'\n')+1;
}
if (((p = strindex(Body,"Subject:")) ||
(p = strindex(Body,"subject:"))) &&
(p == Body || p[-1] == '\n')){
sscanf(skipsp(index(p,':')+1),"%[^\n]",subj);
if (p==Body) Body = index(p,'\n')+1;
}
if (((p = strindex(Body,"Cc:")) ||
(p = strindex(Body,"cc:"))) &&
(p == Body || p[-1] == '\n')){
sscanf(skipsp(index(p,':')+1),"%[^\n]",cc);
if (p==Body) Body = index(p,'\n')+1;
}
}
NXPortFromName("Mail", NULL); // make sure app is launched
[s setSendPort:NXPortFromName("MailSendDemo", NULL)];
call("setTo:",to);
call("setSubject:",subj);
call("setCc:",cc);
call("setBody:",Body);
return self;
}
- print:sender {
[_text printPSCode:sender];
return self;
}
+ new {
me = self = [[Storm alloc] init];
return self;
}
- free {
[self logout:self];
return [super free];
}
- appDidInit:sender {
openDefaults();
if (FirstUse()) [license show:self],
strcpy(DefaultFont,"Helvetica-Bold"),
strcpy(DefaultFontSize,"18.0");
[attachB performClick:sender];
return self;
}
- appWillTerminate:sender {
[self logout:self];
writeDefaults();
return self;
}
@end